home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cmln0986.arc / BLOCKA.MOD < prev    next >
Text File  |  1986-01-31  |  16KB  |  543 lines

  1. procedure BLOCK( FSYS:SYMSET; ISFUN:boolean; LEVEL:integer );
  2.  
  3. type CONREC = record case TP: TYPES of
  4.                 INTS,CHARS,BOOLS: (I: INTEGER);
  5.                 REALS: (R: REAL)
  6.               end;
  7.  
  8. var DX  : INTEGER;   (* data allocation index     *)
  9.     PRT : INTEGER;   (* T-index of this procedure *)
  10.     PRB : INTEGER;   (* B-index of this procedure *)
  11.     X   : INTEGER;
  12.  
  13.  
  14. procedure ENTERARRAY( TP: TYPES; L,H: INTEGER );
  15. begin
  16.   if L > H then ERROR(27);
  17.   if ( ABS(L) > XMAX ) OR ( ABS(H) > XMAX ) then begin
  18.     ERROR(27);
  19.     L := 0;
  20.     H := 0;
  21.   end;
  22.   if A = AMAX then FATAL(4) else begin
  23.     A := A+1;
  24.     with ATAB[A] do begin
  25.       INXTYP := TP;
  26.       LOW := L;
  27.       HIGH := H
  28.     end;
  29.   end;
  30. end; { ENTERARRAY }
  31.  
  32. procedure ENTERBLOCK;
  33. begin
  34.   if B = BMAX then FATAL(2) else begin
  35.     B := B+1;
  36.     BTAB[B].LAST := 0;
  37.     BTAB[B].LASTPAR := 0;
  38.   end;
  39. end; { ENTERBLOCK }
  40.  
  41. procedure ENTERREAL(X: REAL);
  42. begin
  43.   if C2 = C2MAX-1 then FATAL(3) else begin
  44.     RCONST[C2+1] := X;
  45.     C1 := 1;
  46.     while RCONST[C1] <> X do  C1 := C1+1;
  47.     if C1 > C2 then C2 := C1
  48.   end;
  49. end; { ENTERREAL }
  50.  
  51. procedure SKIP( FSYS: SYMSET; N: INTEGER );
  52. begin
  53.   ERROR(N);
  54.   SKIPFLAG := TRUE;
  55.   while NOT ( SY IN FSYS ) do INSYMBOL;
  56.   if SKIPFLAG then ENDSKIP;
  57. end; { SKIP }
  58.  
  59. procedure TEST(S1,S2: SYMSET; N: INTEGER);
  60. begin
  61.   if NOT (SY IN S1) then SKIP(S1+S2,N);
  62. end; { TEST }
  63.  
  64. procedure TESTSEMICOLON;
  65. begin
  66.   if SY = SEMICOLON then INSYMBOL else begin
  67.     ERROR(14);
  68.     if SY IN [COMMA,COLON] then INSYMBOL
  69.   end;
  70.   TEST([IDENT]+BLOCKBEGSYS, FSYS, 6)
  71. end; { TESTSEMICOLON }
  72.  
  73. procedure ENTER( ID: ALFA; K: OBJECT );
  74. var J,L: INTEGER;
  75. begin
  76.   if T = TMAX then FATAL(1) else begin
  77.     TAB[0].NAME := ID;
  78.     J := BTAB[DISPLAY[LEVEL]].LAST;
  79.     L := J;
  80.     while TAB[J].NAME <> ID do  J := TAB[J].LINK;
  81.     if J <> 0 then ERROR(1) else begin
  82.       T := T+1;
  83.       with TAB[T] do begin
  84.         NAME := ID;
  85.         LINK := L;
  86.         OBJ  := K;
  87.         TYP  := NOTYP;
  88.         REF  := 0;
  89.         LEV  := LEVEL;
  90.         ADR  := 0;
  91.       end;
  92.       BTAB[DISPLAY[LEVEL]].LAST := T;
  93.     end;
  94.   end;
  95. end; { enter }
  96.  
  97. function LOC( ID: ALFA ): INTEGER;
  98. var I,J: INTEGER;     (* locate identifier, ID, in table *)
  99. begin
  100.   I := LEVEL;
  101.   TAB[0].NAME := ID;  (* sentinel *)
  102.   repeat
  103.     J := BTAB[DISPLAY[I]].LAST;
  104.     while TAB[J].NAME <> ID do  J := TAB[J].LINK;
  105.     I := I-1;
  106.   until (I<0) OR (J<>0);
  107.   if J = 0 then ERROR(0);
  108.   LOC := J;
  109. end; { LOC }
  110.  
  111. procedure ENTERVARIABLE;
  112. begin
  113.   if SY = IDENT then begin
  114.     ENTER(ID,VARIABLE);
  115.     INSYMBOL;
  116.   end else ERROR(2);
  117. end; { ENTERVARIABLE }
  118.  
  119. procedure CONSTANT(FSYS: SYMSET; var C: CONREC);
  120. var X, SIGN: INTEGER;
  121. begin
  122.   C.TP := NOTYP;
  123.   C.I  := 0;
  124.   TEST(CONSTBEGSYS, FSYS, 50);
  125.   if SY IN CONSTBEGSYS then begin
  126.     if SY = CHARCON then begin
  127.       C.TP := CHARS;
  128.       C.I  := INUM;
  129.       INSYMBOL;
  130.     end else begin
  131.       SIGN := 1;
  132.       if SY IN [PLUS,MINUS] then begin
  133.         if SY = MINUS then SIGN := -1;
  134.         INSYMBOL;
  135.       end;
  136.       if SY = IDENT then begin
  137.         X := LOC(ID);
  138.         if X <> 0 then if TAB[X].OBJ <> KONSTANT then ERROR(25)
  139.         else begin
  140.           C.TP := TAB[X].TYP;
  141.           if C.TP = REALS then C.R := SIGN*RCONST[TAB[X].ADR]
  142.                           else C.I := SIGN*TAB[X].ADR
  143.         end;
  144.         INSYMBOL;
  145.       end else if SY = INTCON then begin
  146.         C.TP := INTS; C.I := SIGN*INUM;
  147.         INSYMBOL
  148.     end else if SY = REALCON then begin
  149.       C.TP := REALS;
  150.       C.R  := SIGN * RNUM;
  151.       INSYMBOL;
  152.       end else SKIP(FSYS,50);
  153.     end;
  154.     TEST(FSYS, [], 6);
  155.   end;
  156. end; { CONSTANT }
  157.  
  158.  procedure TYP( FSYS : SYMSET; var TP : TYPES; var RF, SZ : INTEGER);
  159.  var X: INTEGER;
  160.      ELTP: TYPES; ELRF: INTEGER;
  161.      ELSZ, OFFSET, T0,T1: INTEGER;
  162.  
  163.    procedure ARRAYTYP(var AREF,ARSZ: INTEGER);
  164.    var ELTP: TYPES;
  165.        LOW, HIGH: CONREC;
  166.        ELRF, ELSZ: INTEGER;
  167.    begin
  168.      CONSTANT([COLON,RBRACK,RPARENT,OFSY]+FSYS, LOW);
  169.      if LOW.TP = REALS then begin
  170.        ERROR(27);
  171.        LOW.TP := INTS;
  172.        LOW.I := 0;
  173.      end;
  174.      if SY = COLON then INSYMBOL else ERROR(13);
  175.      CONSTANT([RBRACK,COMMA,RPARENT,OFSY]+FSYS, HIGH);
  176.      if HIGH.TP <> LOW.TP then begin
  177.        ERROR(27);
  178.        HIGH.I := LOW.I;
  179.      end;
  180.      ENTERARRAY(LOW.TP, LOW.I, HIGH.I);
  181.      AREF := A;
  182.      if SY = COMMA then begin
  183.        INSYMBOL;
  184.        ELTP := ARRAYS;
  185.        ARRAYTYP(ELRF,ELSZ)
  186.      end else begin
  187.        if SY = RBRACK then INSYMBOL else begin
  188.          ERROR(12);
  189.          if SY = RPARENT then INSYMBOL;
  190.        end;
  191.        if SY = OFSY then INSYMBOL else ERROR(8);
  192.        TYP(FSYS,ELTP,ELRF,ELSZ);
  193.      end;
  194.      with ATAB[AREF] do begin
  195.        ARSZ := (HIGH-LOW+1)*ELSZ;
  196.        SIZE := ARSZ;
  197.        ELTYP := ELTP;
  198.        ELREF := ELRF;
  199.        ELSIZE := ELSZ;
  200.      end;
  201.    end; { ARRAYTYP }
  202.  
  203.  begin { TYP }
  204.    TP := NOTYP;
  205.    RF := 0;
  206.    SZ := 0;
  207.    TEST(TYPEBEGSYS, FSYS, 10);
  208.    if SY IN TYPEBEGSYS then begin
  209.      if SY = IDENT then begin
  210.        X := LOC(ID);
  211.        if X <> 0 then with TAB[X] do
  212.          if OBJ <> TYPE1 then ERROR(29) else begin
  213.            TP := TYP;
  214.            RF := REF;
  215.            SZ := ADR;
  216.            if TP = NOTYP then ERROR(30);
  217.          end;
  218.          INSYMBOL;
  219.        end else
  220.        if SY = ARRAYSY then begin
  221.          INSYMBOL;
  222.          if SY = LBRACK then INSYMBOL else begin
  223.            ERROR(11);
  224.            if SY = LPARENT then INSYMBOL
  225.          end;
  226.          TP := ARRAYS;
  227.          ARRAYTYP(RF,SZ)
  228.        end else begin { RECORDS }
  229.          INSYMBOL;
  230.          ENTERBLOCK;
  231.          TP := RECORDS;
  232.          RF := B;
  233.          if LEVEL = LMAX then FATAL(5);
  234.          LEVEL := LEVEL+1;
  235.          DISPLAY[LEVEL] := B;
  236.          OFFSET := 0;
  237.          while NOT (SY IN FSYS-[SEMICOLON,COMMA,IDENT]+[ENDSY]) do begin
  238.            if SY = IDENT then begin   (* field section *)
  239.              T0 := T;
  240.              ENTERVARIABLE;
  241.              while SY = COMMA do begin
  242.                INSYMBOL;
  243.                ENTERVARIABLE
  244.              end;
  245.              if SY = COLON then INSYMBOL else ERROR(5);
  246.              T1 := T;
  247.              TYP(FSYS+[SEMICOLON,ENDSY,COMMA,IDENT],ELTP,ELRF,ELSZ);
  248.              while T0 < T1 do begin
  249.                T0 := T0+1;
  250.                with TAB[T0] do begin
  251.                  TYP    := ELTP;
  252.                  REF    := ELRF;
  253.                  NORMAL := TRUE;
  254.                  ADR    := OFFSET;
  255.                  OFFSET := OFFSET + ELSZ;
  256.                end;
  257.              end;
  258.            end;
  259.            if SY <> ENDSY then begin
  260.              if SY = SEMICOLON then INSYMBOL else begin
  261.                ERROR(14);
  262.                if SY = COMMA then INSYMBOL;
  263.              end;
  264.              TEST([IDENT,ENDSY,SEMICOLON], FSYS, 6);
  265.            end;
  266.          end;
  267.          BTAB[RF].VSIZE := OFFSET;
  268.          SZ := OFFSET;
  269.          BTAB[RF].PSIZE := 0;
  270.          INSYMBOL;
  271.          LEVEL := LEVEL-1;
  272.        end;
  273.        TEST(FSYS, [], 6);
  274.      end;
  275.    end; { TYP }
  276.  
  277.    procedure PARAMETERLIST;     (* formal parameter list *)
  278.    var TP            :   TYPES;
  279.        RF, SZ, X, T0 : INTEGER;
  280.        VALPAR        : BOOLEAN;
  281.    begin
  282.      INSYMBOL;
  283.      TP := NOTYP;
  284.      RF := 0;
  285.      SZ := 0;
  286.      TEST([IDENT, VARSY], FSYS+[RPARENT], 7);
  287.      while SY in [IDENT,VARSY] do begin
  288.        if SY <> VARSY then VALPAR := TRUE else begin
  289.          INSYMBOL;
  290.          VALPAR := FALSE
  291.        end;
  292.        T0 := T;
  293.        ENTERVARIABLE;
  294.        while SY = COMMA do begin
  295.          INSYMBOL;
  296.          ENTERVARIABLE;
  297.        end;
  298.        if SY = COLON then begin
  299.          INSYMBOL;
  300.          if SY <> IDENT then ERROR(2) else begin
  301.            X := LOC(ID);
  302.            INSYMBOL;
  303.            if X <> 0 then with TAB[X] do
  304.              if OBJ <> TYPE1 then ERROR(29) else begin
  305.                TP := TYP;
  306.                RF := REF;
  307.                if VALPAR then SZ := ADR else SZ := 1
  308.              end;
  309.            end;
  310.            TEST([SEMICOLON,RPARENT], [COMMA,IDENT]+FSYS, 14)
  311.          end else ERROR(5);
  312.          while T0 < T do begin
  313.            T0 := T0+1;
  314.            with TAB[T0] do begin
  315.              TYP := TP;
  316.              REF := RF;
  317.              NORMAL := VALPAR;
  318.              ADR := DX;
  319.              LEV := LEVEL;
  320.              DX := DX + SZ
  321.            end
  322.          end;
  323.          if SY <> RPARENT then begin
  324.            if SY = SEMICOLON then INSYMBOL else begin
  325.              ERROR(14);
  326.              if SY = COMMA then INSYMBOL
  327.            end;
  328.            TEST([IDENT,VARSY], [RPARENT]+FSYS, 6)
  329.          end
  330.        end; { while }
  331.      if SY = RPARENT then begin
  332.        INSYMBOL;
  333.        TEST( [ SEMICOLON, COLON ], FSYS, 6)
  334.      end else ERROR(4)
  335.    end; { PARAMETERLIST }
  336.  
  337.    procedure CONSTDECLARATION;
  338.    var C: CONREC;
  339.    begin
  340.      INSYMBOL;
  341.      TEST( [IDENT], BLOCKBEGSYS, 2);
  342.      while SY = IDENT do begin
  343.        ENTER( ID, KONSTANT );
  344.        INSYMBOL;
  345.        if SY = EQL then INSYMBOL else begin
  346.          ERROR(16);
  347.          if SY = BECOMES then INSYMBOL;
  348.        end;
  349.        CONSTANT( [SEMICOLON,COMMA,IDENT]+FSYS, C );
  350.        TAB[T].TYP := C.TP;
  351.        TAB[T].REF := 0;
  352.        if C.TP = REALS then begin
  353.          ENTERREAL( C.R );
  354.          TAB[T].ADR := C1;
  355.        end else TAB[T].ADR := C.I;
  356.        TESTSEMICOLON;
  357.      end;
  358.    end; { CONSTDECLARATION }
  359.  
  360.    procedure TYPEDECLARATION;
  361.    var TP        :   TYPES;
  362.        RF, SZ, T1: INTEGER;
  363.    begin
  364.      INSYMBOL;
  365.      TEST( [IDENT], BLOCKBEGSYS, 2);
  366.      while SY = IDENT do begin
  367.        ENTER( ID, TYPE1 );
  368.        T1 := T;
  369.        INSYMBOL;
  370.        if SY = EQL then INSYMBOL else begin
  371.          ERROR(16);
  372.          if SY = BECOMES then INSYMBOL
  373.        end;
  374.        TYP([SEMICOLON,COMMA,IDENT]+FSYS, TP, RF, SZ);
  375.        with TAB[T1] do begin
  376.          TYP := TP;
  377.          REF := RF;
  378.          ADR := SZ
  379.        end;
  380.        TESTSEMICOLON;
  381.      end;
  382.    end; { TYPEDECLARATION }
  383.  
  384.    procedure VARDECLARTION;
  385.    var T0, T1, RF, SZ : INTEGER;
  386.        TP             :   TYPES;
  387.    begin
  388.      INSYMBOL;
  389.      while SY = IDENT do begin
  390.        T0 := T;
  391.        ENTERVARIABLE;
  392.        while SY = COMMA do begin
  393.          INSYMBOL;
  394.          ENTERVARIABLE;
  395.        end;
  396.        if SY = COLON then INSYMBOL else ERROR(5);
  397.        T1 := T;
  398.        TYP( [SEMICOLON,COMMA,IDENT]+FSYS, TP, RF, SZ );
  399.        while T0 < T1 do begin
  400.          T0 := T0+1;
  401.          with TAB[T0] do begin
  402.            TYP := TP;
  403.            REF := RF;
  404.            LEV := LEVEL;
  405.            ADR := DX;
  406.            NORMAL := TRUE;
  407.            DX := DX + SZ;
  408.          end;
  409.        end;
  410.        TESTSEMICOLON;
  411.      end;
  412.    end; { VARDECLARTION }
  413.  
  414.    procedure PROCDECLARATION;
  415.    var ISFUN: BOOLEAN;
  416.    begin
  417.      ISFUN := ( SY = FUNCSY );
  418.      INSYMBOL;
  419.      if SY <> IDENT then begin
  420.        ERROR(2);
  421.        ID := '          '
  422.      end;
  423.      if ISFUN then ENTER( ID, FUNKTION ) else ENTER( ID, PROZEDURE );
  424.      TAB[T].NORMAL := TRUE;
  425.      INSYMBOL;
  426.      block( [SEMICOLON]+FSYS, ISFUN, LEVEL+1 );
  427.      if SY = SEMICOLON then INSYMBOL else ERROR(14 );
  428.      EMIT(32+ORD(ISFUN))  { EXIT }
  429.    end; { procedure DECLARATION }
  430.  
  431. (*---------------------------------------------------------STATEMENT--*)
  432.  
  433.    procedure STATEMENT( FSYS : SYMSET );
  434.    var I : INTEGER;
  435.        X : ITEM;
  436.      procedure EXPRESSION( FSYS : SYMSET; var X: ITEM ); forward;
  437.  
  438.      procedure SELECTOR( FSYS: SYMSET; var V:ITEM );
  439.      var X: ITEM; A,J: INTEGER;
  440.      begin  (* SY IN [LPARENT, LBRACK, PERIOD] *)
  441.        repeat
  442.          if SY = PERIOD then begin
  443.          INSYMBOL;        (* field selector *)
  444.          if SY <> IDENT then ERROR(2) else begin
  445.            if V.TYP <> RECORDS then ERROR(31)
  446.            else begin (* search field identifier *)
  447.              J := BTAB[V.REF].LAST;
  448.              TAB[0].NAME := ID;
  449.              while TAB[J].NAME <> ID do J := TAB[J].LINK;
  450.              if J = 0 then ERROR(0);
  451.              V.TYP := TAB[J].TYP;
  452.              V.REF := TAB[J].REF;
  453.              A := TAB[J].ADR;
  454.              if A <> 0 then EMIT1(9,A);
  455.            end;
  456.            INSYMBOL;
  457.          end;
  458.        end else begin  (* array selector *)
  459.          if SY <> LBRACK then ERROR(11);
  460.          repeat
  461.            INSYMBOL;
  462.            EXPRESSION(FSYS+[COMMA,RBRACK], X);
  463.            if V.TYP <> ARRAYS then ERROR(28) else begin
  464.              A := V.REF;
  465.              if ATAB[A].INXTYP <> X.TYP then ERROR(26)
  466.                else if ATAB[A].ELSIZE = 1 then EMIT1(20,A) else EMIT1(21,A);
  467.              V.TYP := ATAB[A].ELTYP;
  468.              V.REF := ATAB[A].ELREF;
  469.            end;
  470.            until SY <> COMMA;
  471.            if SY = RBRACK then INSYMBOL else begin
  472.              ERROR(12);
  473.              if SY = RPARENT then INSYMBOL
  474.            end;
  475.          end;
  476.        until NOT ( SY IN [ LBRACK, LPARENT, PERIOD ] );
  477.        TEST( FSYS, [], 6 );
  478.      end; { SELECTOR }
  479.  
  480.      procedure CALL( FSYS: SYMSET; I: INTEGER );
  481.      var X            : ITEM;
  482.          LASTP, CP, K : INTEGER;
  483.      begin
  484.        EMIT1(18,I);  (* mark stack *)
  485.        LASTP := BTAB[TAB[I].REF].LASTPAR;
  486.        CP := I;
  487.        if SY = LPARENT then begin (* actual parameter list *)
  488.          repeat
  489.            INSYMBOL;
  490.            if CP >= LASTP then ERROR(39) else begin
  491.              CP := CP+1;
  492.              if TAB[CP].NORMAL then begin  (*  value parameter *)
  493.                EXPRESSION( FSYS+[COMMA,COLON,RPARENT], X );
  494.                if X.TYP=TAB[CP].TYP then begin
  495.                  if X.REF <> TAB[CP].REF then ERROR(36)
  496.                    else if X.TYP = ARRAYS then EMIT1(22,ATAB[X.REF].SIZE)
  497.                      else if X.TYP = RECORDS
  498.                        then EMIT1(22,BTAB[X.REF].VSIZE)
  499.                end else if (X.TYP=INTS) AND (TAB[CP].TYP=REALS)
  500.                  then EMIT1(26,0) else if X.TYP<>NOTYP then ERROR(36);
  501.              end else begin  (* variable parameter *)
  502.                if SY <> IDENT then ERROR(2) else begin
  503.                  K := LOC(ID);
  504.                  INSYMBOL;
  505.                  if K <> 0 then begin
  506.                    if TAB[K].OBJ <> VARIABLE then ERROR(37);
  507.                    X.TYP := TAB[K].TYP;
  508.                    X.REF := TAB[K].REF;
  509.                    if TAB[K].NORMAL then EMIT2( 0,TAB[K].LEV, TAB[K].ADR )
  510.                                     else EMIT2( 1,TAB[K].LEV, TAB[K].ADR );
  511.                    if SY IN [ LBRACK, LPARENT, PERIOD ]
  512.                      then SELECTOR(FSYS+[COMMA,COLON,RPARENT], X);
  513.                    if ( X.TYP<>TAB[CP].TYP ) OR ( X.REF<>TAB[CP].REF )
  514.                      then ERROR(36);
  515.                  end;
  516.                end;
  517.              end;
  518.            end;
  519.            TEST( [COMMA,RPARENT], FSYS, 6 );
  520.          until SY <> COMMA;
  521.          if SY = RPARENT then INSYMBOL else ERROR(4);
  522.        end;
  523.        if CP < LASTP then ERROR(39); (* too few actual parameters *)
  524.        EMIT1( 19, BTAB[TAB[I].REF].PSIZE-1 );
  525.        if TAB[I].LEV < LEVEL then EMIT2( 3, TAB[I].LEV, LEVEL )
  526.      end; { CALL }
  527.  
  528.      function RESULTTYPE( A,B : TYPES ): TYPES;
  529.      begin
  530.         if ( A > REALS ) OR ( B > REALS ) then begin
  531.           ERROR(33);
  532.           RESULTTYPE := NOTYP;
  533.         end else if (A=NOTYP) OR (B=NOTYP) then RESULTTYPE := NOTYP
  534.           else if A=INTS then if B=INTS then RESULTTYPE := INTS
  535.             else begin
  536.               RESULTTYPE := REALS;
  537.               EMIT1(26,1);
  538.             end else begin
  539.               RESULTTYPE := REALS;
  540.             if B=INTS then EMIT1(26,0)
  541.           end;
  542.       end; { RESULTTYPE }
  543.